home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / cool / ge_cool.lha / GE_COOL2.1 / src / Handle / Handle.h next >
C/C++ Source or Header  |  1992-06-12  |  9KB  |  298 lines

  1. //
  2. // Copyright (C) 1992 General Electric Company.
  3. //
  4. // Permission is granted to any individual or institution to use, copy, modify,
  5. // and distribute this software, provided that this complete copyright and
  6. // permission notice is maintained, intact, in all copies and supporting
  7. // documentation.
  8. //
  9. // General Electric Company provides this software "as is" without
  10. // express or implied warranty.
  11. //
  12. // Created: VDN 03/25/92 -- Initial design
  13. //
  14. // Handle<Type> works with Shared mixin on the object to provide 
  15. // a very simple scheme of memory management with reference count.
  16. // Handles to objects are stored in containers or other data structures,
  17. // instead of pointers to objects, if these objects are shared.
  18. // If your design of the object hierarchy has layers, from the root O1
  19. // to the leaves On, parent node Oi should store Oj, or a handle to Oj,
  20. // for automatic deletion of all the nodes in the tree when
  21. // the root O1 is deleted. In essence, you design an acyclic graph
  22. // for your hierarchy. Nodes can be shared with reference count.
  23. // Backward pointers that create cycles in your network should be broken
  24. // up by storing pointers instead of handles. Note that pointers stored in 
  25. // COOL containers are not deleted, while objects are.
  26. //
  27. // Be aware: Empty handles, just as NULL pointers, can create segmentation 
  28. // faults.
  29. //
  30. // Reference:
  31. // 1. Stroupstrup(1991) C++ programming language, 2nd ed, section 13.9.
  32. // 2. Coplien(1992) Advanced C++ programming techniques and idioms.
  33.  
  34.  
  35. #ifndef HANDLEH
  36. #define HANDLEH
  37.  
  38.  
  39. template <class Type> 
  40. class CoolHandle<Type> {
  41.  
  42.   typedef CoolHandle<Type> Type##H;        // short names for handle
  43.   typedef Type*            Type##P;        // pointer
  44.   typedef Type&            Type##R;        // reference
  45.   
  46. public:
  47.   inline CoolHandle<Type> ();            // Empty constructor
  48.   inline CoolHandle<Type> (Type* optr);        // construct hdl from ptr
  49.   inline CoolHandle<Type> (Type& obj);        // construct hdl from obj
  50.   inline CoolHandle<Type> (const CoolHandle<Type>& h); // copy constructor
  51.   
  52.   inline ~CoolHandle<Type>();            // destructor
  53.   
  54.   inline Type* operator-> ();            // dereference
  55.   
  56.   inline CoolHandle<Type>& operator= (Type* optr); // assign to another ptr
  57.   inline CoolHandle<Type>& operator= (Type& obj);  // assign to obj reference
  58.   inline CoolHandle<Type>& operator= (const CoolHandle<Type>& h); // to hdl
  59.   
  60.   inline friend Type* ptr (CoolHandle<Type>&);    // convert to ptr
  61.   inline friend Type& ref (CoolHandle<Type>&);    // convert to reference
  62.   inline friend CoolHandle<Type> hdl (Type* optr=NULL); // convert to hdl
  63.   
  64.   inline operator Type*();            // automatic conversion to ptr
  65.   inline operator Type&();            // automatic conversion to ref
  66.  
  67. #define DECLARE_HANDLE_OPERATOR(op)                          \
  68.   inline friend Boolean operator op (const CoolHandle<Type>&,               \
  69.                      const CoolHandle<Type>&);
  70.   DECLARE_HANDLE_OPERATOR(==)
  71.   DECLARE_HANDLE_OPERATOR(!=)
  72.   DECLARE_HANDLE_OPERATOR(<=)
  73. #undef DECLARE_HANDLE_OPERATOR
  74.  
  75.   inline friend ostream& operator<< (ostream&, const CoolHandle<Type>&);
  76.   inline friend ostream& operator<< (ostream&, const CoolHandle<Type>*);
  77.  
  78. private:
  79.   Type* rep;                    // pointer to shared obj
  80.  
  81.   inline void null_pointer_error (const char* fcn, const char* type);
  82. };
  83.  
  84. // Handle() -- Empty constructor
  85. // Input:             ptr
  86. // Output:            None
  87.  
  88. template<class Type>
  89. inline CoolHandle<Type>::CoolHandle<Type>()
  90. : rep(NULL) {}                    // pointer is NULL
  91.  
  92. // Handle() -- Default constructor from a pointer to object, inc count.
  93. // Input:             ptr
  94. // Output:            None
  95.  
  96. template<class Type>
  97. inline CoolHandle<Type>::CoolHandle<Type>(Type* optr) 
  98. : rep(optr) {
  99.   CoolShared::reference(this->rep);        // inc count on shared obj
  100. }
  101.  
  102. // Handle() -- Constructor from an object, inc count.
  103. // Input:             reference
  104. // Output:            None
  105.  
  106. template<class Type>
  107. inline CoolHandle<Type>::CoolHandle<Type>(Type& obj) 
  108. : rep(&obj) {
  109.   obj.reference();                // inc count on shared obj
  110. }
  111.  
  112. // Handle (handle&) -- Copy constructor from another handle
  113. // Input:             handle to be copied
  114. // Output:            None
  115.  
  116. template<class Type>
  117. inline CoolHandle<Type>::CoolHandle<Type>(const CoolHandle<Type>& h) 
  118. : rep(h.rep) {
  119.   CoolShared::reference(this->rep);        // inc count on shared obj
  120. }
  121.  
  122. // ~Handle  -- Destructor for Handle class, dec count and free object.
  123. // Input:              None
  124. // Output:             None
  125.  
  126. template<class Type>
  127. inline CoolHandle<Type>::~CoolHandle<Type>() {
  128.   if (CoolShared::dereference(this->rep) == 0)    
  129.     delete rep;                    // dec count on obj & delete
  130. }
  131.  
  132. // operator-> -- Dereference overloaded, to make handle look like pointer.
  133. // Input:              None
  134. // Output:             pointer to object.
  135.  
  136. template<class Type>
  137. inline Type* CoolHandle<Type>::operator->() {
  138.   return this->rep;                
  139. }
  140.  
  141.  
  142. // operator= -- Assignment to another pointer, check for aliasing.
  143. // Input:              pointer to object
  144. // Output:             handle on lhs of =
  145.  
  146. template<class Type>
  147. inline CoolHandle<Type>& CoolHandle<Type>::operator=(Type* optr) {
  148.   if (this->rep != optr) {            // aliasing -> premature delete
  149.     if (CoolShared::dereference(this->rep)==0)
  150.       delete this->rep;                // dec count on old obj & delete
  151.     this->rep = optr;
  152.     CoolShared::reference(this->rep);        // inc count on shared obj
  153.   }
  154.   return *this;
  155. }
  156.  
  157.  
  158. // operator=(Type&) -- Assignment to another object reference
  159. // Input:              reference to object
  160. // Output:             handle on lhs of =
  161.  
  162. template<class Type>
  163. inline CoolHandle<Type>& CoolHandle<Type>::operator=(Type& obj) {
  164.   if (this->rep != &obj) {            // aliasing cause premature delete
  165.     if (CoolShared::dereference(this->rep) == 0)
  166.       delete this->rep;                // dec count on old obj & delete
  167.     this->rep = &obj;
  168.     obj.reference();                // inc count on shared obj
  169.   }
  170.   return *this;
  171. }
  172.  
  173. // operator= -- Assignment to another handle
  174. // Input:              handle on rhs of =
  175. // Output:             handle on lhs of =
  176.  
  177. template<class Type>
  178. inline CoolHandle<Type>& CoolHandle<Type>::operator=(const CoolHandle<Type>& h) {
  179.   if (this->rep != h.rep) {            // aliasing cause premature delete
  180.     if (CoolShared::dereference(this->rep) == 0)
  181.       delete this->rep;                // dec count on old obj & delete
  182.     this->rep = h.rep;
  183.     CoolShared::reference(this->rep);        // inc count on shared obj
  184.   }
  185.   return *this;
  186. }
  187.  
  188. // ptr  -- Manual conversion to pointer
  189. // Input:              handle to object
  190. // Output:             pointer to object
  191.  
  192. template<class Type> CoolHandle {
  193. inline Type* ptr (CoolHandle<Type>& h) {
  194.   return h.rep;
  195. }}
  196.  
  197. // ref  -- Manual conversion to reference
  198. // Input:              handle to object
  199. // Output:             ref to object
  200.  
  201. template<class Type> CoolHandle {
  202. inline Type& ref (CoolHandle<Type>& h) {
  203. #if ERROR_CHECKING
  204.     if (!h.rep)
  205.       h.null_pointer_error("ref", #Type);
  206. #endif
  207.   return *(h.rep);
  208. }}
  209.  
  210. // Handle hdl (Type*) -- Manual conversion to handle, returned by value.
  211. //                     A temporary handle is created and deleted by compiler.
  212. // Input:              pointer to object
  213. // Output:             handle to object
  214.  
  215. template<class Type> CoolHandle {
  216. inline CoolHandle<Type> hdl(Type* optr) {
  217.   CoolHandle<Type> h(optr);            // handle with given optr
  218.   return h;                    // copy on return by value
  219. }}
  220.  
  221. // operator Type*  -- Automatic conversion to pointer
  222. //                     Be careful not to store and delete ptrs outside of handles.
  223. // Input:              handle to object
  224. // Output:             pointer to object
  225.  
  226. template<class Type> 
  227. inline CoolHandle<Type>::operator Type* () {
  228.   return this->rep;
  229. }
  230.  
  231.  
  232. // operator Type&  -- Automatic conversion to reference
  233. // Input:              handle to object
  234. // Output:             reference to object
  235.  
  236. template<class Type> 
  237. inline CoolHandle<Type>::operator Type& () {
  238. #if ERROR_CHECKING
  239.     if (!this->rep)
  240.       this->null_pointer_error("operator Type&", #Type);
  241. #endif
  242.   return *(this->rep);
  243. }
  244.  
  245. // Operator== -- Overload comparison operators for handles. Compare pointers.
  246. // Input:             handles 
  247. // Ouput:             Boolean
  248.  
  249. #define IMPLEMENT_HANDLE_OPERATOR(op)                          \
  250. template<class Type> CoolHandle {                          \
  251. inline Boolean operator op (const CoolHandle<Type>& h1,               \
  252.                 const CoolHandle<Type>& h2) {              \
  253.   return h1.rep op h2.rep;                              \
  254. }}
  255.  
  256. IMPLEMENT_HANDLE_OPERATOR(==)
  257. IMPLEMENT_HANDLE_OPERATOR(!=)
  258. IMPLEMENT_HANDLE_OPERATOR(<=)
  259.  
  260.  
  261. #undef IMPLEMENT_HANDLE_OPERATOR
  262.   
  263.  
  264. // operator<< -- print handle object to ostream.
  265. // Input:              ostream and handle to object
  266. // Output:             ostream
  267.  
  268. template<class Type> CoolHandle {
  269. inline ostream& operator<< (ostream& os, const CoolHandle<Type>& h) {
  270.   Type* r = h.rep;
  271.   if (r) 
  272.     return os << *r;
  273.   else
  274.     return os << "Empty";
  275. }}
  276.  
  277.  
  278. // operator<< -- print pointer to a handle to ostream.
  279. // Input:              ostream and pointer to handle 
  280. // Output:             ostream
  281.  
  282. template<class Type> CoolHandle {
  283. inline ostream& operator<< (ostream& os, const CoolHandle<Type>* h) {
  284.   return os << *h;
  285. }}
  286.  
  287. template<class Type>
  288. inline void CoolHandle<Type>::null_pointer_error (const char* fcn, 
  289.                           const char* type) {
  290.   //RAISE (Error, SYM(CoolHandle), SYM(NullPointer))
  291.   printf ("CoolHandle<%s>::%s: Pointer inside handle is NULL.\n",
  292.       type, fcn);
  293.   abort ();
  294. }
  295.  
  296. #endif                        // HANDLEH
  297.  
  298.